package com.ruoyi.youtobe.service.impl;

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.DateTime;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.*;
import com.ruoyi.until.CheckUtilsImp;
import com.ruoyi.until.ImageDownloadUtil;
import com.ruoyi.youtobe.domain.VideoInfoVO;
import com.ruoyi.youtobe.domain.YoutobeChannelInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Title:
 * @author: WYJ
 * @date: 2025/11/5
 */
@Slf4j
public class YoutubeVideoFetcher {
    private static final String API_KEY = "AIzaSyDHzJe68qi-rHXd5ENPsgozNtOcLPpW-Wk"; // 替换为你的API密钥
    private static final String CHANNEL_URL = "https://www.youtube.com/@Battle-Cinema/videos";

    public static void main(String[] args) {
        try {
            YouTube youtube = new YouTube.Builder(
                    GoogleNetHttpTransport.newTrustedTransport(),
                    JacksonFactory.getDefaultInstance(),
                    null)
                    .setApplicationName("youtube-video-info-fetcher")
                    .build();

            // 1. 从频道URL提取频道ID
            String channelId = extractChannelId(youtube, null);
            if (channelId == null) {
                System.out.println("Failed to extract channel ID.");
                return;
            }

            // 2. 获取频道的上传播放列表ID
            String uploadPlaylistId = getUploadPlaylistId(youtube, channelId);
            if (uploadPlaylistId == null) {
                System.out.println("Failed to get upload playlist ID.");
                return;
            }

            // 3. 从播放列表获取视频ID列表
            //List<String> videoIds = getVideoIdsFromPlaylist(youtube, uploadPlaylistId, new VideoInfoIO());

            // 4. 批量获取视频详情（包含统计信息和本地化信息）
            //List<Video> videoDetails = getVideoDetails(youtube, videoIds);
            List<Video> videoDetails = new ArrayList<>(16);
            // 5. 打印结果
            for (Video video : videoDetails) {
                // 获取默认标题
                String defaultTitle = video.getSnippet().getTitle();

                // 获取本地化标题
                Map<String, VideoLocalization> localizations = video.getLocalizations();
                String chineseTitle = getLocalizedTitle(localizations, "zh-Hans", "zh-CN", "zh-TW");
                String englishTitle = getLocalizedTitle(localizations, "en", "en-US", "en-GB");

                // 播放量
                String viewCount = video.getStatistics().getViewCount() != null ?
                        video.getStatistics().getViewCount().toString() : "N/A";

                // 发布时间
                String publishTime = video.getSnippet().getPublishedAt().toString();

                // 封面图 (使用中等尺寸)
                String thumbnailUrl = video.getSnippet().getThumbnails().getMedium().getUrl();

                System.out.println("视频ID: " + video.getId());
                System.out.println("默认标题: " + defaultTitle);
                System.out.println("中文标题: " + (chineseTitle != null ? chineseTitle : "无"));
                System.out.println("英文标题: " + (englishTitle != null ? englishTitle : "无"));
                System.out.println("播放量: " + viewCount);
                System.out.println("发布时间: " + publishTime);
                System.out.println("封面图: " + thumbnailUrl);
                System.out.println("----------------------------");
            }

        } catch (GeneralSecurityException | IOException e) {
            e.printStackTrace();
        }
    }

    public static List<VideoInfoVO> getVideoInfoVOByIo(YoutobeChannelInfo params) {
        List<VideoInfoVO> re = new ArrayList<>(16);
        try {
            YouTube youtube = new YouTube.Builder(
                    GoogleNetHttpTransport.newTrustedTransport(),
                    JacksonFactory.getDefaultInstance(),
                    null)
                    .setApplicationName("youtube-video-info-fetcher")
                    .build();

            // 1. 从频道URL提取频道ID
            String channelId = params.getChannelId();
            if (StringUtils.isBlank(params.getChannelId())) {
                String channelUrl = "https://www.youtube.com/" + params.getChannelUrl() + "/videos";
                channelId = extractChannelId(youtube, channelUrl);
            }
            if (channelId == null) {
                log.info("Failed to extract channel ID .");
                return re;
            }
            log.info("频道ID {}", channelId);

            // 2. 获取频道的上传播放列表ID
            String uploadPlaylistId = params.getPlayListId();
            if (StringUtils.isBlank(params.getPlayListId())) {
                uploadPlaylistId = getUploadPlaylistId(youtube, channelId);
            }
            if (uploadPlaylistId == null) {
                log.info("Failed to get upload playlist ID. .");
                return re;
            }
            log.info("传播放列表ID {}", uploadPlaylistId);
            // 3. 从播放列表获取视频ID列表 批量获取视频详情（包含统计信息和本地化信息）
            List<Video> videoDetails = getVideoIdsFromPlaylist(youtube, uploadPlaylistId, params);
            log.info("videoDetails : {}", videoDetails.size());
            // 5. 打印结果
            for (Video video : videoDetails) {
                VideoInfoVO vo = getVideoInfoVOByVideo(video);
                // 获取默认标题
                String defaultTitle = video.getSnippet().getTitle();

                // 获取本地化标题
                Map<String, VideoLocalization> localizations = video.getLocalizations();
                String chineseTitle = getLocalizedTitle(localizations, "zh-Hans", "zh-CN", "zh-TW");
                String englishTitle = getLocalizedTitle(localizations, "en", "en-US", "en-GB");

                // 播放量
                Long viewCount = video.getStatistics().getViewCount() != null ?
                        video.getStatistics().getViewCount().longValue() : 0l;

                // 发布时间
                DateTime publishTime = video.getSnippet().getPublishedAt();
                vo.setChineseTitle(chineseTitle != null ? chineseTitle : "无");
                vo.setEnglishTitle(englishTitle != null ? englishTitle : "无");
                vo.setChannelName(params.getChannelName());
                re.add(vo);
            }

        } catch (GeneralSecurityException | IOException e) {
            e.printStackTrace();
        }
        return re;
    }

    public static void getChannelInfo(YoutobeChannelInfo params) {
        List<VideoInfoVO> re = new ArrayList<>(16);
        try {
            YouTube youtube = new YouTube.Builder(
                    GoogleNetHttpTransport.newTrustedTransport(),
                    JacksonFactory.getDefaultInstance(),
                    null)
                    .setApplicationName("youtube-video-info-fetcher")
                    .build();

            // 1. 从频道URL提取频道ID
            String channelUrl = "https://www.youtube.com/" + params.getChannelKey() + "/videos";
            String channelId = extractChannelId(youtube, channelUrl);
            if (channelId == null) {
                log.info("Failed to extract channel ID .");
            }
            log.info("频道ID {}", channelId);
            params.setChannelId(channelId);
            // 2. 获取频道的上传播放列表ID
            String uploadPlaylistId = getUploadPlaylistId(youtube, channelId);
            if (uploadPlaylistId == null) {
                log.info("Failed to get upload playlist ID. .");
            }
            log.info("传播放列表ID {}", uploadPlaylistId);
            params.setPlayListId(uploadPlaylistId);
        } catch (GeneralSecurityException | IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @description: 通过频道自定义URL获取频道ID
     * @author: WYJ
     * @date: 2025/11/12
     * @param:
     */
    private static String extractChannelId(YouTube youtube, String channelUrl) throws IOException {
        String customUrl = "";
        if (StringUtils.isBlank(channelUrl)) {
            customUrl = CHANNEL_URL.substring(CHANNEL_URL.indexOf("@") + 1, CHANNEL_URL.indexOf("/videos"));

        } else {
            customUrl = channelUrl.substring(channelUrl.indexOf("@") + 1, channelUrl.indexOf("/videos"));

        }

        YouTube.Search.List search = youtube.search().list("snippet");
        search.setKey(API_KEY);
        search.setQ(customUrl);
        search.setType("channel");
        search.setMaxResults(1L);

        SearchListResponse response = search.execute();
        if (response.getItems() != null && !response.getItems().isEmpty()) {
            return response.getItems().get(0).getId().getChannelId();
        }
        return null;
    }

    // 通过频道ID获取上传播放列表ID
    private static String getUploadPlaylistId(YouTube youtube, String channelId) throws IOException {
        YouTube.Channels.List channelsListRequest = youtube.channels().list("contentDetails");
        channelsListRequest.setKey(API_KEY);
        channelsListRequest.setId(channelId);

        ChannelListResponse response = channelsListRequest.execute();
        if (response.getItems() != null && !response.getItems().isEmpty()) {
            return response.getItems().get(0).getContentDetails().getRelatedPlaylists().getUploads();
        }
        return null;
    }

    // 通过播放列表ID获取视频ID列表
    private static List<Video> getVideoIdsFromPlaylist(YouTube youtube, String playlistId, YoutobeChannelInfo params) throws IOException {

        List<Video> videos = new ArrayList<>();
        YouTube.PlaylistItems.List playlistItemsRequest = youtube.playlistItems().list("snippet");
        playlistItemsRequest.setKey(API_KEY);
        playlistItemsRequest.setPlaylistId(playlistId);
        //playlistItemsRequest.s
        // 限制获取数量，避免超出配额
        playlistItemsRequest.setMaxResults(10L);
        if (params.getVideoNum() != null) {
            playlistItemsRequest.setMaxResults(params.getVideoNum()+10);
        }
        if (params.getVideoNum() <= 50) {
            // 执行请求
            PlaylistItemListResponse response = playlistItemsRequest.execute();
            List<String> videoIdList = new ArrayList<>(16);
            for (PlaylistItem item : response.getItems()) {
                videoIdList.add(item.getSnippet().getResourceId().getVideoId());
            }
            List<Video> videoDetails = getVideoDetails(youtube, videoIdList);
            videos.addAll(videoDetails);
        } else {
            //通过下一页获取全部数据
            String nextPageToken = null;
            do {
                // 设置下一页令牌（首次请求后）
                if (nextPageToken != null) {
                    playlistItemsRequest.setPageToken(nextPageToken);
                }

                // 执行请求
                PlaylistItemListResponse response = playlistItemsRequest.execute();
                List<String> videoIdList = new ArrayList<>(16);
                for (PlaylistItem item : response.getItems()) {
                    videoIdList.add(item.getSnippet().getResourceId().getVideoId());
                }
                List<Video> videoDetails = getVideoDetails(youtube, videoIdList);
                videos.addAll(videoDetails);
                // 将当前页数据加入总列表
                //allPlaylistItems.addAll(response.getItems());

                // 获取下一页令牌，若无则循环结束

                nextPageToken = response.getNextPageToken();

            } while (nextPageToken != null && videos.size() < params.getVideoNum()+20); // 重要：根据分页令牌循环
        }
        //===
        //PlaylistItemListResponse response = playlistItemsRequest.execute();


        // 4. 批量获取视频详情（包含统计信息和本地化信息）
        return videos;
    }

    // 通过视频ID列表批量获取视频详情
    private static List<Video> getVideoDetails(YouTube youtube, List<String> videoIds) throws IOException {
        if (videoIds.isEmpty()) {
            return new ArrayList<>();
        }

        String videoIdString = String.join(",", videoIds);

        // 关键：请求snippet, statistics, 和 localizations
        //YouTube.Videos.List videosRequest = youtube.videos().list("snippet,statistics");
        YouTube.Videos.List videosRequest = youtube.videos().list("snippet,statistics,localizations");
        videosRequest.setKey(API_KEY);
        videosRequest.setId(videoIdString);
        VideoListResponse response = videosRequest.execute();
        return response.getItems();
    }

    public static VideoInfoVO getVideoDetailsByVideoId(String videoId) {
        if (StringUtils.isBlank(videoId)) {
            return null;
        }
        try {
            YouTube youtube = new YouTube.Builder(
                    GoogleNetHttpTransport.newTrustedTransport(),
                    JacksonFactory.getDefaultInstance(),
                    null)
                    .setApplicationName("youtube-video-info-fetcher")
                    .build();
            //String videoIdString = String.join(",", videoIds);

            // 关键：请求snippet, statistics, 和 localizations
            //YouTube.Videos.List videosRequest = youtube.videos().list("snippet,statistics");
            YouTube.Videos.List videosRequest = youtube.videos().list("snippet,statistics,localizations");
            videosRequest.setKey(API_KEY);
            videosRequest.setId(videoId);
            VideoListResponse response = videosRequest.execute();
            List<Video> items = response.getItems();
            if (CheckUtilsImp.listIsEmpty(items)) {
                return null;
            }

            Video video = items.get(0);
            VideoInfoVO re = getVideoInfoVOByVideo(video);
            return re;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static VideoInfoVO getVideoInfoVOByVideo(Video video){
        VideoInfoVO vo = new VideoInfoVO();
        // 获取默认标题
        String defaultTitle = video.getSnippet().getTitle();

        // 获取本地化标题
        Map<String, VideoLocalization> localizations = video.getLocalizations();
        // 播放量
        Long viewCount = video.getStatistics().getViewCount() != null ?
                video.getStatistics().getViewCount().longValue() : 0l;

        // 发布时间
        DateTime publishTime = video.getSnippet().getPublishedAt();
        // 封面图 (使用中等尺寸)
        String thumbnailUrl = video.getSnippet().getThumbnails().getMedium().getUrl();
        vo.setVideoId(video.getId());
        vo.setDefaultTitle(defaultTitle);
        vo.setViewCount(viewCount);
        vo.setPublishTime(publishTime);
        vo.setThumbnailUrl(thumbnailUrl);
        String localPath = ImageDownloadUtil.downloadImage(vo.getThumbnailUrl());
        vo.setLocalUrl(localPath);
        String key = "";
        String title = vo.getDefaultTitle();
        int index = title.indexOf("#");
        if (index != -1) {
            key = title.substring(index);
        }
        vo.setTitleKey(key);
        return vo;
    }
    // 从本地化数据中获取指定语言的标题
    private static String getLocalizedTitle(Map<String, VideoLocalization> localizations, String... languageCodes) {
        if (localizations == null) return null;

        for (String languageCode : languageCodes) {
            VideoLocalization localization = localizations.get(languageCode);
            if (localization != null && localization.getTitle() != null && !localization.getTitle().isEmpty()) {
                return localization.getTitle();
            }
        }
        return null;
    }
}
